package cn.iocoder.yudao.module.system.controller.admin.datasource;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datasource.core.ChangeDataSourceService;
import cn.iocoder.yudao.framework.datasource.core.DataSourceConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.datasource.SystemDataSourceConfigDO;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.controller.admin.datasource.vo.DataSourceConfigPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.datasource.vo.DataSourceConfigRespVO;
import cn.iocoder.yudao.module.system.controller.admin.datasource.vo.DataSourceConfigSaveReqVO;
import cn.iocoder.yudao.module.system.service.datasource.DataSourceConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 系统数据源配置")
@RestController
@RequestMapping("/system/datasource-config")
@Validated
@Slf4j
public class SystemDataSourceConfigController {

    @Resource(name = "systemDataSourceConfigService")
    private DataSourceConfigService dataSourceConfigService;
    
    @Autowired(required = false)
    private ChangeDataSourceService changeDataSourceService;

    @PostMapping("/create")
    @Operation(summary = "创建数据源配置")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:create')")
    public CommonResult<Long> createDataSourceConfig(@Valid @RequestBody DataSourceConfigSaveReqVO createReqVO) {
        return success(dataSourceConfigService.createDataSourceConfig(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新数据源配置")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:update')")
    public CommonResult<Boolean> updateDataSourceConfig(@Valid @RequestBody DataSourceConfigSaveReqVO updateReqVO) {
        dataSourceConfigService.updateDataSourceConfig(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除数据源配置")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('system:datasource-config:delete')")
    public CommonResult<Boolean> deleteDataSourceConfig(@RequestParam("id") Long id) {
        dataSourceConfigService.deleteDataSourceConfig(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得数据源配置")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:query')")
    public CommonResult<DataSourceConfigRespVO> getDataSourceConfig(@RequestParam("id") Long id) {
        SystemDataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id);
        return success(BeanUtils.toBean(dataSourceConfig, DataSourceConfigRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得数据源配置分页")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:query')")
    public CommonResult<PageResult<DataSourceConfigRespVO>> getDataSourceConfigPage(@Valid DataSourceConfigPageReqVO pageReqVO) {
        PageResult<SystemDataSourceConfigDO> pageResult = dataSourceConfigService.getDataSourceConfigPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, DataSourceConfigRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出数据源配置 Excel")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:export')")
    public void exportDataSourceConfigExcel(DataSourceConfigPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<SystemDataSourceConfigDO> list = dataSourceConfigService.getDataSourceConfigPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "数据源配置.xls", "数据", DataSourceConfigRespVO.class,
                        BeanUtils.toBean(list, DataSourceConfigRespVO.class));
    }

    @PostMapping("/test-connection")
    @Operation(summary = "测试数据源连接")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:query')")
    public CommonResult<Boolean> testConnection(@RequestParam("id") Long id) {
        return success(dataSourceConfigService.testConnection(id));
    }

    @PostMapping("/switch")
    @Operation(summary = "切换数据源")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('system:datasource-config:switch')")
    public CommonResult<Boolean> switchDataSource(@RequestParam("id") Long id) {
        if (changeDataSourceService == null) {
            log.warn("数据源切换服务未初始化");
            return success(false);
        }

        SystemDataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id);
        if (dataSourceConfig == null) {
            return success(false);
        }

        // 转换为框架的数据源配置对象
        DataSourceConfigDO config = new DataSourceConfigDO(
                String.valueOf(dataSourceConfig.getId()),
                dataSourceConfig.getUrl(),
                dataSourceConfig.getUsername(),
                dataSourceConfig.getPassword(),
                dataSourceConfig.getType()
        );

        try {
            changeDataSourceService.changeDS(config);
            log.info("成功切换到数据源: {}", dataSourceConfig.getName());
            return success(true);
        } catch (Exception e) {
            log.error("切换数据源失败: {}", dataSourceConfig.getName(), e);
            return success(false);
        }
    }

}